/*
 * Created on 2004-01-29
 */
package org.opencube.util;

import org.opencube.data.Database;


/**
 * The parameter representation. Stores type, and mode values.
 * 
 * @author <a href="mailto:maciek@fingo.pl">FINGO - Maciej Mroczko</a>
 * TODO: comment
 */
public class Parameter
{
	/**
	 * The parameter name parts separator 
	 */
	public static final String PARAMETER_PARTS_SEPARATOR = "_";
	/**
	 * The paramater mode constant: in = 'in'.
	 */
	public static final String MODE_IN = "in";
	
	/**
	 * The paramater mode constant: out = 'out'.
	 */
	public static final String MODE_OUT = "out";
	
	/**
	 * The paramater mode constant: inout = 'inout'.
	 */
	public static final String MODE_INOUT = "inout";
	
	/**
	 * All allowed MODES for the parameters
	 */
	public static final String[] ALLOWED_MODES = new String[]
	{
		MODE_IN,
		MODE_INOUT,
		MODE_OUT,
	};

	/* The full name of this parameter */
	private String name = null;
	/* The value of the parameter */
	private Object value = null;
	/* The exact name of the BoundVariable */
	private String exactName = null;
	/* The parameter type */
	private String type = Database.TYPE_STRING;
	/* The parameter mode */
	private String mode = MODE_IN;
	/* The indexes of this parameter in the statement */
	private int[] indexes;
	
	/**
	 * The constructor.
	 * Parses the name and sets the members.
	 */		
	public Parameter( String parameterName, Object value, int[] indexes )
	{
		this.name = parameterName;
		this.value = value;
		this.indexes = indexes;
		
		int index = parameterName.indexOf( PARAMETER_PARTS_SEPARATOR );
		if( index > 0 && index != parameterName.length() -1 )
		{
			String pMode = parameterName.substring( 0, index );
			if( isValidMode( pMode ) )
			{
				parameterName = parameterName.substring( index + 1 );
				index = parameterName.indexOf( PARAMETER_PARTS_SEPARATOR );
				if( index > 0 )
				{
					String pType = parameterName.substring( 0, index );
					if( isValidType( pType ) )
					{
						this.mode = pMode;
						this.type = pType;
						if( index != parameterName.length() - 1 )
						{
							this.exactName = parameterName.substring( index + 1 );
						}
					} 
				}
			}
		}
	}
	
	/**
	 * Returns the parameter name.
	 * 
	 * @return String
	 */
	public String getName()
	{
		return this.name;
	}
	
	/**
	 * Returns the value of the parameter.
	 * 
	 * @return Object
	 */
	public Object getValue()
	{
		return this.value;
	}
	
	public int[] getIndexes()
	{
		return this.indexes;
	}		
	
	/**
	 * Returns <code>true</code> if the <code>mode</code> and <code>type</code> were fetched successfully.
	 * 
	 * @return boolean
	 */
	public boolean isConform()
	{
		return this.type != null && this.mode != null;
	}
	
	/**
	 * Returns the exact name of the parameter or full name, if the parameter is not conform.
	 * 
	 * @return String
	 */
	public String getExactName()
	{
		return this.exactName;
	}
	
	/**
	 * Returns mode string - <code>null</code> if this parameter is not conform.
	 * 
	 * @return String
	 */
	public String getMode()
	{
		return this.mode;
	}
	
	/**
	 * Returns type string - <code>null</code> if this parameter is not conform.
	 * 
	 * @return String
	 */
	public String getType()
	{
		return this.type;
	}
	
	/* Verifies, if the given mode is one of the allowed */
	private boolean isValidMode( String mode2check )
	{
		return inArray(  mode2check, ALLOWED_MODES );
	}

	/* Verifies, if the given type is one of the allowed */
	private boolean isValidType( String type2check )
	{
		return inArray(  type2check, Database.ALLOWED_TYPES );
	}
	
	/* Searches for the given string in the array */
	private boolean inArray( String string, String[] array )
	{
		for( int i = 0; array != null && i < array.length; i++ )
		{
			if( array[ i ].equals( string ) )
			{
				return true;
			}
		}
		return false;
	}
	
	/* The string representation of this parameter */
	public String toString()
	{
		StringBuffer sb = new StringBuffer();
		sb.append( "name: " + name + Constants.STR_NEW_LINE );
		sb.append( "value: " + value + Constants.STR_NEW_LINE );
		sb.append( "exact name: " + exactName + Constants.STR_NEW_LINE );
		sb.append( "type: " + type + Constants.STR_NEW_LINE );
		sb.append( "mode: " + mode + Constants.STR_NEW_LINE );
		sb.append( "indexes: " );
		for( int i = 0; i < indexes.length; i++ )
		{
			if( i > 0 )
			{
				sb.append( ", " );
			}
			sb.append( indexes[ i ] );
		}
		sb.append( Constants.STR_NEW_LINE );
		
		return sb.toString();
	}
}